package com.cy.comstore.controller;


import com.cy.comstore.controller.ex.*;
import com.cy.comstore.entity.User;
import com.cy.comstore.service.IUserService;
import com.cy.comstore.service.ex.InsertException;
import com.cy.comstore.service.ex.UsernameDuplicateException;
import com.cy.comstore.util.JsonResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author xsn
 * @since 2023-03-03
 */
@RestController
@RequestMapping("users")
public class UserController extends BaseController{
    @Autowired
    private IUserService userService;

    @RequestMapping("reg")
    public JsonResult<Void> reg(User user){
        userService.reg(user);
        return new JsonResult<Void>(OK);
        /*JsonResult<Void> result = new JsonResult<>();
        try {
            userService.reg(user);
            //没有出现异常的提示
            result.setState(200);
            result.setMessage("用户注册成功");
        } catch (UsernameDuplicateException e) {
            result.setState(4000);
            result.setMessage("用户名被占用");
        }catch (InsertException e){
            result.setState(5000);
            result.setMessage("注册时产生未知异常");
        }
        return result;*/
    }

    @RequestMapping("login")
    public JsonResult<User> login(String username, String password, HttpSession session) {
        // 调用业务对象的方法执行登录，并获取返回值
        User data = userService.login(username, password);
        //向session对象中完成数据的绑定（此时的session是全局的），任何位置都可以访问
        session.setAttribute("uid",data.getUid());
        session.setAttribute("username",data.getUsername());

        //获取session中绑定的数据
        System.out.println(getUidFromSession(session));
        System.out.println(getUsernameFromSession(session));
        return new JsonResult<User>(OK,data);
    }

    /**
     * 修改用户密码
     * @param oldPassword
     * @param newPassword
     * @param session
     * @return
     */
    @RequestMapping("changePwd")
    //当给的是非pojo的属性值时，需要和表单中的name保持一致
    public JsonResult<Void> changePwd(String oldPassword,String newPassword,HttpSession session){
        Integer uid = getUidFromSession(session);
        String username = getUsernameFromSession(session);

        userService.changepwd(uid,newPassword,username,oldPassword);
        return new JsonResult<Void>(OK);
    }

    @RequestMapping("getByUid")
    public JsonResult<User> getByUid(HttpSession session){
        Integer uid = getUidFromSession(session);
        User user = userService.getByUid(uid);
        return new JsonResult<User>(OK,user);
    }
    /**
     *修改个人资料
     * @param user
     * @param session
     * @return
     */
    @RequestMapping("changeInfo")
    //前端只动态传递user对象的gender，phone，email，要修改用户信息，需要获取uid、username和修改时间与用户
    public JsonResult<Void> changeInfo(User user,HttpSession session){
        userService.changeInfo(getUidFromSession(session),getUsernameFromSession(session),user);
        return new JsonResult<Void>(OK);
    }

    /** 头像文件大小的上限值(10MB) */
    public static final int AVATAR_MAX_SIZE = 10 * 1024 * 1024;
    /** 允许上传的头像的文件类型 */
    public static final List<String> AVATAR_TYPES = new ArrayList<String>();
    /** 初始化允许上传的头像的文件类型 */
    //使用静态块给list集合做初始化
    //ctrl+d向下复制
    static {
        AVATAR_TYPES.add("image/jpeg");
        AVATAR_TYPES.add("image/png");
        AVATAR_TYPES.add("image/bmp");
        AVATAR_TYPES.add("image/gif");
    }

    /**
     *  @RequestParm("value="参数名",required=true/false),将请求方法绑定到你控制器的方法参数上
     * 接口是SpringMVC提供一个接口，这个接口为我们包装了获取文件类型的数据(任何类型的file 都可以接收)，
     * SpringBoot 它又整合了SpringMVC，只需要在处理请求的方法参数列表上声明一个参数类型为MultipartFile的参数
     * 然后SpringBoot自动将传递给服务的文件数据赋值赋值给这个参数
     * @RequestParam 表示请求中的参数，将请求中的参数注入请求处理方法的某个参数上，如果名称不一致则可以使用RequestParam注解进行标记和映射
     *
     */
    @PostMapping("changeAvatar")
    public JsonResult<String> changeAvatar  (@RequestParam("file") MultipartFile file, HttpSession session) {
        //发现空文件、大文件、文件类型不匹配异常-》获取文件存储目录（也可以手动创建如D:/upload/）
        // -》UUID随机生成文件名-》创建目录名+文件名的文件对象，表示保存的头像文件-》将前端传过来的文件数据注入到文件对象中

        // 判断上传的文件是否为空
        if (file.isEmpty()){// 是：抛出异常
            throw new FileEmptyException("文件为空");
        }
        // 判断上传的文件大小是否超出限制值
        if (file.getSize() > AVATAR_MAX_SIZE) { // getSize()：返回文件的大小，以字节为单位
            // 是：抛出异常
            throw new FileSizeException("不允许上传超过" + (AVATAR_MAX_SIZE / 1024) + "KB的头像文件");
        }

        // 判断上传的文件类型是否超出限制
        String contentType = file.getContentType();
        // boolean contains(Object o)：当前列表若包含某元素，返回结果为true；若不包含该元素，返回结果为false
        if (!AVATAR_TYPES.contains(contentType)) {
            // 是：抛出异常
            throw new FileTypeException("不支持使用该类型的文件作为头像，允许的文件类型：" + AVATAR_TYPES);
        }
/*================================================================================================================*/
        //项目部署到哪里就把图片文件存储在哪里的upload文件夹下   //上传的文件：../upload/文件.png
        // 获取当前项目的绝对磁盘路径（获取上下文upload的路径）
       /* System.out.println(session.getServletContext());
        System.out.println(session.getServletContext().getRealPath("upload"));
       String parent = session.getServletContext().getRealPath("upload");*/
        String parent ="D:/demo/store/upload/";  //图片路径保存在tomcat那里就可以显示，如果是自定义文件夹路径src就不能显示,报错404http://localhost:8080/upload/BD6CD548-D497-43E6-B034-1EE767A33894.jpg
        //tomcat临时路径每次都会该边，所以每次启动服务器parent都不一样，可以把parent改为绝对路径然后在配置包下写一个资源映射。
        File dir = new File(parent);
        //目录不存在则创建
        if (!dir.exists()){
            dir.mkdirs();
        }
/*================================================================================================================*/
        //为了防止重名发生覆盖，采取随机生成文件名的方式UUID
//获取原始文件名
        String originalFilename = file.getOriginalFilename();
        //获取原始文件名的后缀(与文件类型image/jpeg不同)
        //originalFilename.lastIndexOf("."）代表这个小数点所在的位置 返回int类型
        //截取文件名小数点往后的内容
        String substring = originalFilename.substring(originalFilename.lastIndexOf("."));

        String fileName = UUID.randomUUID().toString().toUpperCase()+substring;
/*================================================================================================================*/
        // 创建目录名+文件名的文件对象，表示保存的头像文件
        File dest = new File(dir, fileName); //是一个空文件
        // 执行保存头像文件，把参数file的数据写入到这个空文件中
        try {
            file.transferTo(dest);
        } catch (IllegalStateException e) {
            // 抛出异常
            throw new FileStateException("文件状态异常，可能文件已被移动或删除");
        } catch (IOException e) {
            // 抛出异常
            throw new FileUploadIOException("上传文件时读写错误，请稍后重新尝试");
        }
/*================================================================================================================*/
        // 返回头像路径只需要访问相对路径就可以，无需绝对路径
       //由于选择的目录为项目部署的路径，所以相对路径为
        String avatar="/upload/"+fileName;
        // 将头像写入到数据库中
        userService.updateAvatar(getUidFromSession(session),avatar,getUsernameFromSession(session));
        // 返回成功和头像路径给前端，用于头像的展示
        return new JsonResult<String>(OK,avatar);
    }
}

